package com.region.loadbalancer.group;

import com.region.loadbalancer.listener.ConnectionListener;
import com.region.loadbalancer.monitor.stat.DetectionConnection;
import com.region.loadbalancer.monitor.stat.SocketDetectionConnection;
import com.region.loadbalancer.policy.BalancerPolicy;
import com.region.loadbalancer.policy.RandomPolicy;

import java.util.Collections;
import java.util.List;

/**
 * Group of Servers
 *
 * @author liujieyu
 * @date 2023/5/24 23:40
 * @desciption
 */
public class GroupServer {

    /**
     * Name of service group
     */
    private String groupName;

    /**
     * The Collection of Servers
     */
    private List<Server> servers;

    /**
     * Balancer Policy
     */
    private BalancerPolicy policy;

    /**
     * Listening the status of server
     */
    private List<ConnectionListener> listeners;

    /**
     * Detection Connection Status
     */
    private DetectionConnection detectionConnection;

    /**
     * Whether to open the automated scanning service status
     */
    private boolean autoDetect;

    /**
     * Checking the availability of a service before selecting it
     */
    private boolean detectOnBorrow;
    /**
     * The Manager of Group Server
     */
    private GroupServerManager manager;

    private GroupServer(String groupName, List<Server> servers, BalancerPolicy policy, List<ConnectionListener> listeners,
                        DetectionConnection detectionConnection, boolean autoDetect, boolean detectOnBorrow) {
        if (policy == null) {
            policy = new RandomPolicy();
        }
        if (detectionConnection == null) {
            detectionConnection = new SocketDetectionConnection();
        }
        this.groupName = groupName;
        this.servers = servers;
        this.policy = policy;
        this.listeners = listeners;
        this.detectionConnection = detectionConnection;
        this.autoDetect = autoDetect;
        this.detectOnBorrow = detectOnBorrow;
        this.manager = new GroupServerManager(this);
    }

    public void setGroupName(String groupName) {
        this.groupName = groupName;
    }

    public void setServers(List<Server> servers) {
        this.servers = servers;
    }

    public void setPolicy(BalancerPolicy policy) {
        this.policy = policy;
    }

    public void setListeners(List<ConnectionListener> listeners) {
        this.listeners = listeners;
    }

    public void setDetectionConnection(DetectionConnection detectionConnection) {
        this.detectionConnection = detectionConnection;
    }

    public DetectionConnection getDetectionConnection() {
        return detectionConnection;
    }

    protected List<ConnectionListener> getListeners() {
        return listeners;
    }

    public String getGroupName() {
        return groupName;
    }

    public List<Server> getServers() {
        return servers;
    }

    protected BalancerPolicy getPolicy() {
        return policy;
    }

    public GroupServerManager getManager() {
        return manager;
    }

    public boolean isAutoDetect() {
        return autoDetect;
    }

    public boolean isDetectOnBorrow() {
        return detectOnBorrow;
    }

    @Override
    public String toString() {
        StringBuilder string = new StringBuilder();
        string.append("GroupServer{groupName=");
        string.append(groupName);
        string.append(", servers=");
        string.append(servers);
        string.append(", policy=");
        string.append(policy);
        string.append(", listeners=");
        string.append(listeners);
        string.append(", detectionConnection=");
        string.append(detectionConnection);
        string.append(", autoDetect=");
        string.append(autoDetect);
        string.append(", detectOnBorrow=");
        string.append(detectOnBorrow);
        string.append("}");
        return string.toString();
    }

    /**
     * Get Builder of Group Server
     *
     * @return
     */
    public static GroupServerBuilder builder() {
        return new GroupServerBuilder();
    }

    /**
     * The Builder of Group Server
     */
    public static final class GroupServerBuilder {

        private String groupName;

        private List<Server> servers;

        private BalancerPolicy policy;

        private List<ConnectionListener> listeners;

        private DetectionConnection detectionConnection;

        private boolean autoDetect;

        private boolean detectOnBorrow;

        public GroupServerBuilder groupName(String groupName) {
            this.groupName = groupName;
            return this;
        }

        public GroupServerBuilder servers(List<Server> servers) {
            this.servers = servers;
            return this;
        }

        public GroupServerBuilder policy(BalancerPolicy policy) {
            this.policy = policy.deepClone();
            return this;
        }

        public GroupServerBuilder listeners(List<ConnectionListener> listeners) {
            this.listeners = listeners;
            return this;
        }

        public GroupServerBuilder detectionConnection(DetectionConnection detectionConnection) {
            this.detectionConnection = detectionConnection;
            return this;
        }

        public GroupServerBuilder autoDetect(boolean autoDetect) {
            this.autoDetect = autoDetect;
            return this;
        }

        public GroupServerBuilder detectOnBorrow(boolean detectOnBorrow) {
            this.detectOnBorrow = detectOnBorrow;
            return this;
        }

        public GroupServer build() {
            return new GroupServer(groupName, servers, policy, listeners, detectionConnection, autoDetect, detectOnBorrow);
        }
    }
}
